/**
 * C++ 数据流分析查询
 * 基于CodeQL的source到sink分析模式
 * 
 * 输出列：
 *  - source_type: 数据源类型
 *  - source_location: 数据源位置
 *  - sink_type: 数据汇类型  
 *  - sink_location: 数据汇位置
 *  - flow_path: 数据流路径
 *  - flow_length: 流路径长度
 */

import cpp
import semmle.code.cpp.dataflow.DataFlow
import semmle.code.cpp.dataflow.TaintTracking

/**
 * 定义数据源（Source）
 * 包括：用户输入、文件读取、网络接收等
 */
class UserInputSource extends DataFlow::Node {
  UserInputSource() {
    // 函数参数作为用户输入
    exists(Parameter p | this.asParameter() = p) or
    // 标准输入流
    exists(Call call | 
      call.getTarget().hasQualifiedName("std", "cin") and
      this.asExpr() = call
    ) or
    // 文件读取函数
    exists(Call call |
      call.getTarget().hasQualifiedName("std", "ifstream") and
      this.asExpr() = call
    ) or
    // 网络接收函数
    exists(Call call |
      call.getTarget().hasQualifiedName("recv") and
      this.asExpr() = call
    )
  }
}

/**
 * 定义数据汇（Sink）
 * 包括：危险函数调用、文件写入、网络发送等
 */
class DangerousSink extends DataFlow::Node {
  DangerousSink() {
    // 缓冲区操作函数
    exists(Call call |
      call.getTarget().hasQualifiedName("strcpy") or
      call.getTarget().hasQualifiedName("strcat") or
      call.getTarget().hasQualifiedName("sprintf") or
      call.getTarget().hasQualifiedName("gets") and
      this.asExpr() = call
    ) or
    // 系统命令执行
    exists(Call call |
      call.getTarget().hasQualifiedName("system") or
      call.getTarget().hasQualifiedName("exec") and
      this.asExpr() = call
    ) or
    // SQL查询
    exists(Call call |
      call.getTarget().hasQualifiedName("sqlite3_exec") or
      call.getTarget().hasQualifiedName("mysql_query") and
      this.asExpr() = call
    )
  }
}

/**
 * 数据流配置
 */
class DataFlowConfig extends DataFlow::Configuration {
  DataFlowConfig() { this = "DataFlowConfig" }

  override predicate isSource(DataFlow::Node source) {
    source instanceof UserInputSource
  }

  override predicate isSink(DataFlow::Node sink) {
    sink instanceof DangerousSink
  }
}

/**
 * 污点跟踪配置
 */
class TaintConfig extends TaintTracking::Configuration {
  TaintConfig() { this = "TaintConfig" }

  override predicate isSource(DataFlow::Node source) {
    source instanceof UserInputSource
  }

  override predicate isSink(DataFlow::Node sink) {
    sink instanceof DangerousSink
  }
}

/**
 * 主查询：数据流分析
 */
from DataFlowConfig config, DataFlow::Node source, DataFlow::Node sink
where
  config.hasFlow(source, sink)
select
  "UserInput" as source_type,
  source.getLocation().toString() as source_location,
  "DangerousFunction" as sink_type,
  sink.getLocation().toString() as sink_location,
  "DataFlow" as flow_path,
  1 as flow_length

/**
 * 污点分析查询
 */
from TaintConfig config, DataFlow::Node source, DataFlow::Node sink
where
  config.hasFlow(source, sink)
select
  "TaintedInput" as source_type,
  source.getLocation().toString() as source_location,
  "TaintedSink" as sink_type,
  sink.getLocation().toString() as sink_location,
  "TaintFlow" as flow_path,
  1 as flow_length
